package cont;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.util.Duration;
import objects.TimeSelector;
import objects.Track;
import objects.WavClip;
import audioPlayer.AudioPlayer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.sun.javafx.property.adapter.PropertyDescriptor;
import communication.ClipRecord;
import communication.HostCommunication;
import communication.ProjectRecord;
import communication.TrackRecord;
import drawables.Drawable;
import drawables.DrawableManager;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.util.List;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment;
import javafx.stage.WindowEvent;
import objects.AudioClip;
import objects.MP3Clip;
import search.SearchResultFactory;

public class UIController implements Initializable   {
	private static Drawable currentDrawable=null;
        private static Track currentTrack=null;
	private ArrayList<Track> tracks = new ArrayList<Track>();
	private TimeSelector timeSelector = new TimeSelector();
	private final String serverUrl = "http://sharecomposition.appspot.com";
	//private final String serverUrl = "http://127.0.0.1:8888";
	//Image trackBackground;
        
        
        private int mouseX;
        private int mouseY;
	
        private final static int CANVAS_X=3000;
        private final static int CANVAS_Y=282;
        final Canvas canvas = new Canvas(CANVAS_X, CANVAS_Y);
        
	@FXML private TextField artistNameSearch;
	@FXML private AnchorPane trackHolder;
	@FXML private Button playBtn;
	@FXML private Button stopBtn;
	@FXML private Button pauseBtn;
        @FXML private Button shareBtn;
        @FXML private Button saveBtn;
	@FXML private GridPane searchResults;
        @FXML private TextField bpm;
                             
        @FXML private Slider trackVolumeSelector;
        @FXML private Slider trackPanSelector;
        @FXML private ScrollPane trackScrollPane;
        @FXML private Tooltip trackToolTip;
        
        
        private SearchResultFactory srf;
	
	
	public void addTracks(){
		for(int i=0 ; i < 8 ; i++){
			Track t = new Track(0, i* 30 + 30 , null, this);
			tracks.add(t);
		}
	}
	
	
	
	
	
	static int x=0;
	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		
                Image playImage = new Image(getClass().getResourceAsStream("/resources/imgs/playBtn.png"));
                Image stopImage = new Image(getClass().getResourceAsStream("/resources/imgs/stopBtn.png"));
                Image pauseImage = new Image(getClass().getResourceAsStream("/resources/imgs/pauseBtn.png"));
                Image shareImage = new Image(getClass().getResourceAsStream("/resources/imgs/shareBtn.png"));
                Image saveImage = new Image(getClass().getResourceAsStream("/resources/imgs/saveBtn.png"));
                
                //playBtn = new Button("Play" , new ImageView(playImage));
                playBtn.setGraphic(new ImageView(playImage));
                stopBtn.setGraphic(new ImageView(stopImage));
                pauseBtn.setGraphic(new ImageView(pauseImage));
                shareBtn.setGraphic(new ImageView(shareImage));
                saveBtn.setGraphic(new ImageView(saveImage));
                
                        
                playBtn.setTextAlignment(TextAlignment.LEFT);
                
		srf = new SearchResultFactory(searchResults , this);
		addTracks();
		//addClips();
		//addSearchResults();
                addSearchResultsFromHost();
                
                
                
		playBtn.setOnAction(new EventHandler<ActionEvent>() {
			
			@Override
			public void handle(ActionEvent event) {
				AudioPlayer.get().play(tracks);
			}
		});
		
		stopBtn.setOnAction(new EventHandler<ActionEvent>() {
			
			@Override
			public void handle(ActionEvent event) {
				AudioPlayer.get().stop(tracks);
			}
		});
		
                canvas.setOnMouseMoved(new EventHandler<MouseEvent>(){

                @Override
                public void handle(MouseEvent event) {
                    mouseX = (int)event.getX();
                    mouseY = (int)event.getY();
                    
                    //System.out.println(mouseX + " " + mouseY);
                }
                    
                });
                
		canvas.setOnMousePressed(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent e) {
				int X = (int)e.getX();
				int Y = (int)e.getY();
                                if(currentDrawable!=null){
                                    currentDrawable.setSelected(false);
                                }
				currentDrawable = DrawableManager.get().getDrawable(X , Y);
                                if(currentDrawable!=null){
                                    currentDrawable.setSelected(true);
                                    if(e.getButton().equals(MouseButton.SECONDARY)){
                                            currentDrawable.onRightClick(X, Y);
                                    }else if(e.getButton().equals(MouseButton.PRIMARY)){
                                            currentDrawable.onLeftClick(X, Y);
                                    }
                                    
//                                    trackToolTip.setText(serverUrl);
                                }
			}
		});
		
		
		canvas.setOnMouseDragged(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent e) {
				int X = (int)e.getX();
				int Y = (int)e.getY();
				
				if(currentDrawable!=null)
		    		currentDrawable.onDrag(X, Y);
			}
		});
		
		
		canvas.setOnMouseReleased(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent e) {
				int X = (int)e.getX();
				int Y = (int)e.getY();
				
				Drawable dropTarget = DrawableManager.get().getTrack(X , Y );
                                if(dropTarget!=null){
                                    if(currentDrawable!=null){
		    			
                                        dropTarget.onDropReceived(currentDrawable);
                                        currentDrawable.onDrop(dropTarget);
                                        //currentDrawable = null;
                                    }
                                }
				
                        }
		});
                
               trackVolumeSelector.valueProperty().addListener(new ChangeListener<Number>(){

                @Override
                public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                    currentTrack.setVolume(trackVolumeSelector.getValue());
                }
               });
                    
               trackPanSelector.valueProperty().addListener(new ChangeListener<Number>(){

                @Override
                public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                    currentTrack.setBalance(trackPanSelector.getValue());
                }
               });
                
                
		trackHolder.getChildren().add(canvas);
		
		final Timeline animation = new Timeline(
                new KeyFrame(Duration.millis(40),
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent actionEvent) {
                    	canvas.getGraphicsContext2D().clearRect(0, 0, CANVAS_X, CANVAS_Y);
						DrawableManager.get().paint(canvas.getGraphicsContext2D());
                    }
                }));
        bpm.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    AudioPlayer.get().setBPM(Integer.valueOf(bpm.getText()));
                }
            });
        
        
        trackToolTip.setOnShowing(new EventHandler<WindowEvent>(){

                @Override
                public void handle(WindowEvent event) {
                    try {
                        trackToolTip.setAutoHide(false);   
                        trackToolTip.setAutoFix(false);
                        AudioClip ac = (AudioClip)DrawableManager.get().getDrawable(mouseX, mouseY);
                        StringBuilder contents= new StringBuilder();
                        
                        contents.append("Clip name: " + ac.getTitle() + "\n");
                        contents.append("Uploader: " + ac.getUplaoder() + "\n");
                        contents.append("Instrument: " + ac.getInstrument() + "\n");
                        contents.append("Genre: " + ac.getGenre() + "\n");
                        contents.append("BPM: " + ac.getBpm() + "\n");
                        contents.append("Key: " + ac.getKey() + "\n");
                        contents.append("Rating: " + ac.getRating() + "\n");
                        
                        trackToolTip.setText(contents.toString());
                        trackToolTip.setOpacity(1);
                    } catch (Exception e) {
                        trackToolTip.setText("");
                        trackToolTip.setOpacity(0);
                        event.consume();
                        
                    }
                    
                }
            
        });
        
        saveBtn.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    Gson gson = new Gson();
                    //String json = gson.toJson(getProjectRecord());
                    String str = "{\"tracks\":[{\"volume\":0.8,\"balance\":0.0,\"clips\":[{\"id\":\"AMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"info\":\"Drumloop/Chorus-1\",\"genre\":\"Rock\",\"instrument\":\"Drum\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"startTime\":0},{\"id\":\"AMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"info\":\"Drumloop/Chorus-1\",\"genre\":\"Rock\",\"instrument\":\"Drum\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"startTime\":8000},{\"id\":\"AMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"info\":\"Drumloop/Chorus-1\",\"genre\":\"Rock\",\"instrument\":\"Drum\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"startTime\":16000},{\"id\":\"AMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"info\":\"Drumloop/Chorus-1\",\"genre\":\"Rock\",\"instrument\":\"Drum\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv948JVxgr2B8rEfj4fGTH8yfKrJ2Ns0FPAjrr6DETNgwV9upurrinLMQl_z9chj4ftDBtdLrmBGGTatjnhHG8ChQ-314EMp5IKMUxEilcTqQgJ4s-tIdWL5A9PhWt3_DULe2ayrtVhMOI3WgKJVgwRr0Bpfb2A\",\"startTime\":24000}]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[{\"id\":\"AMIfv97kr7Pd7sTw9yil2kguzyH5jxL1DcL5AlqVTW0Do_c-vGScQEQ3RYvDX-Pf9_j3GBIA4iNsD2vhlmWDH-L8qQZ50vs4gUijavtT_cdXn_zudX9pTzI_NADKLMHi7eLx79BiiOym_iVKf5OOOhLwi_ZKLZrtOnRAKVzJSIYqoCZUlTXmlk0\",\"info\":\"Bass-1 note (2 Bars)\",\"genre\":\"Rock\",\"instrument\":\"Electric Bass Guitar\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv97kr7Pd7sTw9yil2kguzyH5jxL1DcL5AlqVTW0Do_c-vGScQEQ3RYvDX-Pf9_j3GBIA4iNsD2vhlmWDH-L8qQZ50vs4gUijavtT_cdXn_zudX9pTzI_NADKLMHi7eLx79BiiOym_iVKf5OOOhLwi_ZKLZrtOnRAKVzJSIYqoCZUlTXmlk0\",\"startTime\":0},{\"id\":\"AMIfv96zA1IfvwD1QTgoZOAQVHW0ewlOS1vF9janquDlnltsquSNUXVlOzh3EppzL7HPJ621jNjlmX3LXANwmBUx9FQGA9tQuZxFqgieomu1f4wjDP3NE5ygkzXGhjR1QKbDZl8BxS--GL8LDeyVX72b5UrxpxQoiw\",\"info\":\"Bass-1/1\",\"genre\":\"Rock\",\"instrument\":\"Electric Bass Guitar\",\"uploader\":\"site-team\",\"url\":\"http://sharecomposition.appspot.com/serve?blob-key\u003dAMIfv96zA1IfvwD1QTgoZOAQVHW0ewlOS1vF9janquDlnltsquSNUXVlOzh3EppzL7HPJ621jNjlmX3LXANwmBUx9FQGA9tQuZxFqgieomu1f4wjDP3NE5ygkzXGhjR1QKbDZl8BxS--GL8LDeyVX72b5UrxpxQoiw\",\"startTime\":4000}]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]},{\"volume\":0.8,\"balance\":0.0,\"clips\":[]}]}";
                    ProjectRecord pr = (ProjectRecord)gson.fromJson(str, ProjectRecord.class);
                    
                    assignProjectRecord(pr);
//                    ArrayList<String> al = new ArrayList<String>();
//                    al.add("HAHA");
//                    al.add("BABA");
//                    String str;
//                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
//                    XMLEncoder encoder = new XMLEncoder(baos);
//                    encoder.writeObject(currentTrack);
//                    encoder.close();
//                    str = baos.toString();
                    
                }
            });
        
        animation.setCycleCount(Animation.INDEFINITE);
        animation.play();
		
		tracks.get(0).onLeftClick(0, 0);
	       
	}
	
	
        
        
        private void addSearchResultsFromHost(){
            for(AudioClip mp3Clip : HostCommunication.get().getClips()){
                srf.addSearchResult(mp3Clip);
            }
        }
        
        public void addAudioClip(int trackIndex , double time , AudioClip audioClip){
            tracks.get(trackIndex).addAudioClip(audioClip, time);
        }
        
        public double getSelectedTime(){
            double res=0;
            long qTime = AudioPlayer.get().getQuantizedTime();
            long qMesur = AudioPlayer.get().getQuantizedMesurment();
            int x = DrawableManager.get().getTrackLine().getX();
            
            res = (double)x / (double)qMesur;
            res *= qTime;
            
            return res;
        }

    public static Drawable getCurrentDrawable() {
        return currentDrawable;
    }

    public static void setCurrentDrawable(Drawable currentDrawable) {
        UIController.currentDrawable = currentDrawable;
    }

    public static Track getCurrentTrack() {
        return currentTrack;
    }

    public static void setCurrentTrack(Track currentTrack) {
        UIController.currentTrack = currentTrack;
    }
        
    
    public void setTrackVolumeSelector(double volume){
        trackVolumeSelector.setValue(volume);
    }
    
    public void setTrackPanSelector(double balance){
        trackPanSelector.setValue(balance);
    }
    
    private ProjectRecord getProjectRecord(){
        ProjectRecord pr = new ProjectRecord();
        for(Track t : tracks)
            pr.tracks.add(t.getTrackRecord());
        
        return pr;
    }
        
    private void assignProjectRecord(ProjectRecord projectRecord){
        int i = 0;
        for(TrackRecord tr : projectRecord.tracks){
            tracks.get(i).setBalance(tr.balance);
            tracks.get(i).setVolume(tr.volume);
            
            for(ClipRecord cr : tr.clips){
                AudioClip mp3Clip = MP3Clip.createFromRecord(cr);
                tracks.get(i).addAudioClip(mp3Clip,cr.getStartTime());
                DrawableManager.get().add(mp3Clip);
            }
            i++;
        }
       
    }

    public Canvas getCanvas() {
        return canvas;
    }
    
    
}
